1 module hunt.templates.rule; 2 3 import std.regex; 4 import std.exception; 5 import std.string; 6 7 import hunt.templates.match; 8 9 void template_engine_throw(string type, string message) { 10 throw new Exception("[Template Engine exception." ~ type ~ "] " ~ message); 11 } 12 13 enum Type { 14 Comment, 15 Condition, 16 ConditionBranch, 17 Expression, 18 Loop, 19 Main, 20 String 21 } 22 23 enum Delimiter { 24 Comment, 25 Expression, 26 LineStatement, 27 Statement 28 } 29 30 enum Statement { 31 Condition, 32 Include, 33 Loop 34 } 35 36 //the order is import 37 enum Function { 38 Not, 39 And, 40 Or, 41 In, 42 Equal, 43 Greater, 44 GreaterEqual, 45 Less, 46 LessEqual, 47 Different, 48 Callback, 49 DivisibleBy, 50 Even, 51 First, 52 Float, 53 Int, 54 Last, 55 Length, 56 Lower, 57 Max, 58 Min, 59 Odd, 60 Range, 61 Result, 62 Round, 63 Sort, 64 Upper, 65 ReadJson, 66 Default 67 } 68 69 enum Condition { 70 ElseIf, 71 If, 72 Else 73 } 74 75 enum Loop { 76 ForListIn, 77 ForMapIn 78 } 79 80 static this() 81 { 82 regex_map_delimiters = [ 83 Delimiter.Statement : ("\\{\\%\\s*(.+?)\\s*\\%\\}"), 84 Delimiter.LineStatement: ("(?:^|\\n)## *(.+?) *(?:\\n|$)"), 85 Delimiter.Expression : ("\\{\\{\\s*(.+?)\\s*\\}\\}"), 86 Delimiter.Comment: ("\\{#\\s*(.*?)\\s*#\\}") 87 ]; 88 } 89 90 __gshared string[Delimiter] regex_map_delimiters; 91 92 enum string[Statement] regex_map_statement_openers = [ 93 Statement.Loop : ("for (.+)"), 94 Statement.Condition : ("if (.+)"), 95 Statement.Include : ("include \"(.+)\"") 96 ]; 97 98 enum string[Statement] regex_map_statement_closers = [ 99 Statement.Loop : ("endfor"), 100 Statement.Condition : ("endif") 101 ]; 102 103 enum string[Loop] regex_map_loop = [ 104 Loop.ForListIn : ("for (\\w+) in (.+)"), 105 Loop.ForMapIn : ("for (\\w+),\\s*(\\w+) in (.+)") 106 ]; 107 108 enum string[Condition] regex_map_condition = [ 109 Condition.If : ("if (.+)"), 110 Condition.ElseIf : ("else if (.+)"), 111 Condition.Else : ("else") 112 ]; 113 114 string function_regex(const string name, int number_arguments) { 115 string pattern = name; 116 pattern ~= "(?:\\("; 117 for (int i = 0; i < number_arguments; i++) { 118 if (i != 0) pattern ~= ","; 119 pattern ~= "(.*)"; 120 } 121 pattern ~= "\\))"; 122 if (number_arguments == 0) { // Without arguments, allow to use the callback without parenthesis 123 pattern ~= "?"; 124 } 125 return "\\s*" ~ pattern ~ "\\s*"; 126 } 127 128 enum string[Function] regex_map_functions = [ 129 Function.Not : "not (.+)", 130 Function.And : "(.+) and (.+)", 131 Function.Or : "(.+) or (.+)", 132 Function.In : "(.+) in (.+)", 133 Function.Equal : "(.+) == (.+)", 134 Function.Greater : "(.+) > (.+)", 135 Function.Less : "(.+) < (.+)", 136 Function.GreaterEqual : "(.+) >= (.+)", 137 Function.LessEqual : "(.+) <= (.+)", 138 Function.Different : "(.+) != (.+)", 139 Function.Default : function_regex("default", 2), 140 Function.DivisibleBy : function_regex("divisibleBy", 2), 141 Function.Even : function_regex("even", 1), 142 Function.First : function_regex("first", 1), 143 Function.Float : function_regex("float", 1), 144 Function.Int : function_regex("int", 1), 145 Function.Last : function_regex("last", 1), 146 Function.Length : function_regex("length", 1), 147 Function.Lower : function_regex("lower", 1), 148 Function.Max : function_regex("max", 1), 149 Function.Min : function_regex("min", 1), 150 Function.Odd : function_regex("odd", 1), 151 Function.Range : function_regex("range", 1), 152 Function.Round : function_regex("round", 2), 153 Function.Sort : function_regex("sort", 1), 154 Function.Upper : function_regex("upper", 1), 155 Function.ReadJson : "\\s*([^\\(\\)]*\\S)\\s*" 156 ]; 157 158 enum ElementNotation { 159 Dot, 160 Pointer 161 };